<?php

/**
 * 本文件用于封装用户相关的查询
 *
 * 查询返回的标准结构如下
 * <code>
 *  array {
 *      "total" => 100, // 当前索引中找到的总数
 *      "start" => 0, // 起始位置
 *      "time" => 100, // 耗时
 *      "total_estimate" => 1000, // 所有索引中估计的总数
 *      "result" => array ( // 命中的结果
 *          array ("user_id" => 2), // 第1个结果
 *          array ("user_id" => 8), // 第2个结果
 *          array ("user_id" => 100) // 第3个结果
 *       ))
 *  }
 * </code>
 * @note	
 * @author    徐鹏程 <xupengcheng@snda.com>
 * @version   0.0.1		2010/03/29
 */

require_once(dirname(__FILE__).'/../../libraries/UCFuncUtils.php');

define('UC_SE_GENDER', 1); // 性别，数字id
define('UC_SE_AGE', 2); // 年龄
define('UC_SE_LOCATION', 3); // 居住地，数字id
define('UC_SE_HOMETOWN', 4); // 出生地，数字id
define('UC_SE_COMPANY', 5); // 公司名
define('UC_SE_UNIVERSITY', 6); // 大学，值必须为一个数组，内容是array(UC_SE_SCHOOL_NAME=>名称,
                                                    //                                                          UC_SE_SCHOOL_YEAR=>入学年份,
													//                                                          UC_SE_SCHOOL_CLASS=>院系)
define('UC_SE_HIGHSCHOOL', 7); // 高中，值必须为一个数组，内容是array(UC_SE_SCHOOL_NAME=>名称,
                                                    //                                                          UC_SE_SCHOOL_YEAR=>入学年份,
													//                                                          UC_SE_SCHOOL_CLASS=>班级)

define('UC_SE_SCHOOL_NAME', 1); // 学校名称
define('UC_SE_SCHOOL_YEAR', 2); // 入学年份
define('UC_SE_SCHOOL_CLASS', 3); // 院系/班级

require_once(dirname(__FILE__).'/../../libraries/UCLibLuceneApi.php');
require_once(dirname(__FILE__).'/../../libraries/UCLibLuceneCondition.php');
require_once(dirname(__FILE__).'/../../libraries/UCLibCodes.php');
require_once(dirname(__FILE__).'/UCModUserInfo.php');
require_once(dirname(__FILE__).'/UCModUserStatistics.php');
require_once(dirname(__FILE__).'/../relation/UCModRelation.php');


class UCModUserSearcher {
	
	protected static $_errorNo  = 0;

	const ERRNO_BAD_PARAMETER = 1;
	const ERRNO_SERVER_ERROR = 2;

	/**
	 * 返回一个查询器
	 */
	protected static function _getSearcher() {
		return new UCLibLuceneApi();
	}

	/**
	 * 查询推荐给我的人
	 * @return 标准返回结构，false如果发生错误
	 */
	public static function getRecommend($user_id, $gender = null, $age = null, $start = 0, $length = 20) {
		$user = UCModUserInfo::getUser($user_id);

		if ($age && $age <= 1) $age = null;


		$cond = new UCLibLuceneCondition();
		$cond->addTerm("user_id", $user_id, UCLibLuceneCondition::OCCUR_MUST_NOT, UCLibLuceneCondition::TYPE_NOT_ANALYZED);

		$cond->addTerm("avatar", "1", UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);

		$relation = new UCModRelation($user_id);
		$follows = $relation->getFollowsDistinct(0, 0);
		if($follows) {
			foreach($follows['entry'] as $entry) {
				if ($entry['fsdid']) {
					$cond->addTerm("user_id", $entry['fsdid'], UCLibLuceneCondition::OCCUR_MUST_NOT, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
				}
			}
		}

		$has_must = false;
		if ($gender) {
			$cond->addTerm("gender", $gender, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
			$has_must = true;
		} else {
			$g = $user->getValue(USERINFO_GENDER);
			if ($g == 1) {
				$has_must = true;
				$cond->addTerm("gender", "2", UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
			} else if ($g == 2) {
				$has_must = true;
				$cond->addTerm("gender", "1", UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
			}
		}
		
		if ($age && $age > 1) {
			$cond->addTerm("age", $age, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
			$has_must = true;
		}
		
		if (!$has_must) {
			$cond->addTerm("gender", "0 1 2", UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_ANALYZED);
		}


		self::_addIP($cond, $user_id);

		$location_id = $user->getValue(USERINFO_LOCATION);
		if ($location_id) $cond->addTerm("location", $location_id, UCLibLuceneCondition::OCCUR_SHOULD, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		$hometown_id = $user->getValue(UC_SE_HOMETOWN);
		if ($hometown_id) $cond->addTerm("hometown", $hometown_id, UCLibLuceneCondition::OCCUR_SHOULD, UCLibLuceneCondition::TYPE_NOT_ANALYZED);


		$searcher = self::_getSearcher();
		$result = $searcher->search($cond, $start, $length);

		if (!$result || !isset($result["error"]) || $result["error"] != 0) {
			self::$_errorNo = self::ERRNO_SERVER_ERROR;
			return false;
		} else {
			if ($start > 0 && $result["length"] == 0 && $result["total_docs"] > 0) {
				$start = mt_rand(0, $result["total_estimate"] - $length);
				if ($start < 0) $start = 0;
				$result = $searcher->search($cond, $start, $length);
				if (!$result || !isset($result["error"]) || $result["error"] != 0) {
					self::$_errorNo = self::ERRNO_SERVER_ERROR;
					return false;
				}
			}
			return $result;
		}
	}

	/**
	 * 按照昵称搜索用户
	 * @return 标准返回结构，false如果发生错误
	 */
	public static function searchByName($nick, $start = 0, $length = 20) {
		$cond = new UCLibLuceneCondition();
		$cond->addTerm("name", $nick, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		$searcher = self::_getSearcher();
		$result = $searcher->search($cond, $start, $length);
		if (!$result || !isset($result["error"]) || $result["error"] != 0) {
			self::$_errorNo = self::ERRNO_SERVER_ERROR;
			return false;
		} else {
			return $result;
		}
	}

	/**
	 * 按照昵称模糊搜索用户
	 * @return 标准返回结构，false如果发生错误
	 */
	public static function searchByNameFuzzy($nick, $gender = null, $age = null, $start = 0, $length = 20) {
		$cond = new UCLibLuceneCondition();
		
		if ($gender) {
			$cond->addTerm("gender", $gender, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		}
		
		if ($age && $age > 1) {
			$cond->addTerm("age", $age, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		}
		
		$cond->addTerm("name_", $nick, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_ANALYZED);
		$searcher = self::_getSearcher();
		$result = $searcher->search($cond, $start, $length);
		if (!$result || !isset($result["error"]) || $result["error"] != 0) {
			self::$_errorNo = self::ERRNO_SERVER_ERROR;
			return false;
		} else {
			return $result;
		}
	}

	/**
	 * 按条件过滤用户
	 * @return 标准返回结构，false如果发生错误
	 */
	public static function searchUser($user_id, $conditions, $start = 0, $length = 20) {
		if (!is_array($conditions)) {
			self::$_errorNo = self::ERRNO_BAD_PARAMETER;
			return false;
		}
		$cond = new UCLibLuceneCondition();
		$cond->addTerm("user_id", $user_id, UCLibLuceneCondition::OCCUR_MUST_NOT, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		foreach ($conditions as $k => $v) {
			if (!$v && !($v === 0)) continue;
			switch ($k) {
				case UC_SE_GENDER:
					$cond->addTerm("gender", $v, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
					break;
				case UC_SE_AGE:
					if ($v > 1)
						$cond->addTerm("age", $v, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
					break;
				case UC_SE_LOCATION:
					$cond->addTerm("location", $v, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
					break;
				case UC_SE_HOMETOWN:
					$cond->addTerm("hometown", $v, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
					break;
				case UC_SE_COMPANY:
					$cond->addTerm("company", $v, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
					break;
				case UC_SE_UNIVERSITY:
					$ret = self::_encodeSchool(1, $v);
					if ($ret === false) {
						self::$_errorNo = self::ERRNO_BAD_PARAMETER;
						return false;
					} else if (!$ret) break;
					$cond->addTerm("school", $ret, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
					break;
				case UC_SE_HIGHSCHOOL:
					$ret = self::_encodeSchool(2, $v);
					if ($ret === false) {
						self::$_errorNo = self::ERRNO_BAD_PARAMETER;
						return false;
					} else if (!$ret) break;
					$cond->addTerm("school", $ret, UCLibLuceneCondition::OCCUR_MUST, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
					break;
				default:
					self::$_errorNo = self::ERRNO_BAD_PARAMETER;
					return false;
			}
		}
		$user = UCModUserInfo::getUser($user_id);
		self::_addIP($cond, $user_id);
		$searcher = self::_getSearcher();
		$result = $searcher->search($cond, $start, $length);
		if (!$result || !isset($result["error"]) || $result["error"] != 0) {
			self::$_errorNo = self::ERRNO_SERVER_ERROR;
			return false;
		} else {
			return $result;
		}
	}

	private static function _convertIP($ip, $islong = true) {
		if ($islong) {
			$ip = UCModUserStatistics::_long2ip($ip);
		}
		$parts = explode(".", $ip);
		if (count($parts) != 4) return null;
		$hex = "";
		foreach ($parts as $i => $v) {
			if ($i >= 3) break;
			if ($v < 16) $hex .= "0";
			$hex .= dechex($v);
		}
		return $hex;
	}

	private static function _encodeSchool($type, $shool) {
		if (!isset($shool[UC_SE_SCHOOL_NAME])) return false;
		if (!$shool[UC_SE_SCHOOL_NAME]) return "";
		$txt = $type . "\n" . $shool[UC_SE_SCHOOL_NAME];
		if (isset($shool[UC_SE_SCHOOL_YEAR]) && $shool[UC_SE_SCHOOL_YEAR]) $txt .= "\n" . $shool[UC_SE_SCHOOL_YEAR];
		if (isset($shool[UC_SE_SCHOOL_CLASS]) && $shool[UC_SE_SCHOOL_CLASS]) $txt .= "\n" . $shool[UC_SE_SCHOOL_CLASS];
		return md5(strtolower($txt));
	}

	private static function _addIP(&$cond, &$user_id) {
		$stat = UCModUserStatistics::getStat($user_id);
		$has_ip = false;
		$ip = $stat->getValue(UC_STAT_LAST_LOGIN_IP_0);
		if ($ip) {
			$has_ip = true;
			$cond->addTerm("ips", self::_convertIP($ip), UCLibLuceneCondition::OCCUR_SHOULD, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		}
		$ip = $stat->getValue(UC_STAT_LAST_LOGIN_IP_1);
		if ($ip) {
			$has_ip = true;
			$cond->addTerm("ips", self::_convertIP($ip), UCLibLuceneCondition::OCCUR_SHOULD, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		}
		$ip = $stat->getValue(UC_STAT_LAST_LOGIN_IP_2);
		if ($ip) {
			$has_ip = true;
			$cond->addTerm("ips", self::_convertIP($ip), UCLibLuceneCondition::OCCUR_SHOULD, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		}
		if (!$has_ip) {
			$cond->addTerm("ips", self::_convertIP(get_client_ip(), false), UCLibLuceneCondition::OCCUR_SHOULD, UCLibLuceneCondition::TYPE_NOT_ANALYZED);
		}
	}

	/**
	 * 获取最后的错误代码
	 * @return 错误代码
	 *  具体含义请看 http://aqyw.sdo.com/projects/uc/wiki/UC%E9%94%99%E8%AF%AF%E4%BB%A3%E7%A0%81%E8%A1%A8
	 */
	public static function getLastErrorNo() {
		return self::$_errorNo;
	}

	public static function getRelationDesc($user1_id, $user2_id) {
		// 在你附近
		$ip_keys = array(UC_STAT_LAST_LOGIN_IP_0, UC_STAT_LAST_LOGIN_IP_1, UC_STAT_LAST_LOGIN_IP_2);
		$ips = array();
		$stat1 = UCModUserStatistics::getStat($user1_id);
		foreach($ip_keys as $k) {
			$ip = $stat1->getValue($k);
			if ($ip) $ips []= self::_convertIP($ip);
		}

		if ($ips) {
			$stat2 = UCModUserStatistics::getStat($user2_id);
			foreach($ip_keys as $k) {
				$ip = $stat2->getValue($k);
				if ($ip) {
					$ip = self::_convertIP($ip);
					if (in_array($ip, $ips)) return "在你附近";
				}
			}
		}

		// 同城有缘人
		$location_id1 = UCModUserInfo::getUser($user1_id)->getValue(USERINFO_LOCATION);
		if ($location_id1) {
			$location_id2 = UCModUserInfo::getUser($user2_id)->getValue(USERINFO_LOCATION);
			if ($location_id1 = $location_id2) return "同城有缘人";
		}

		// 你的老乡
		$howntown_id1 = UCModUserInfo::getUser($user1_id)->getValue(USERINFO_HOMETOWN);
		if ($howntown_id1) {
			$howntown_id2 = UCModUserInfo::getUser($user2_id)->getValue(USERINFO_HOMETOWN);
			if ($howntown_id1 = $howntown_id2) return "你的老乡";
		}

		// 同学
		$schools1 = UCModUserInfo::getUser($user1_id)->getSchoolList();
		if ($schools1) {
			$schools2 = UCModUserInfo::getUser($user2_id)->getSchoolList();
			if ($schools2) {
				$temp = array();
				foreach($schools1 as &$school) {
					$temp []= $school[USERINFO_SCHOOL_TYPE] . $school[USERINFO_SCHOOL_NAME];
				}
				foreach($schools2 as &$school) {
					if (in_array($school[USERINFO_SCHOOL_TYPE] . $school[USERINFO_SCHOOL_NAME], $temp)) {
						return UCLibCodes::$action_types->getName($school[USERINFO_SCHOOL_TYPE])."同学";
					}
				}
			}
		}

		// 同事
		$company1 = UCModUserInfo::getUser($user1_id)->getCompanyList();
		if ($company1) {
			$company2 = UCModUserInfo::getUser($user2_id)->getCompanyList();
			if ($company2) {
				$temp = array();
				foreach($company1 as &$company) {
					$temp []= $company[USERINFO_COMPANY_NAME];
				}
				foreach($company2 as &$company) {
					if (in_array($company[USERINFO_COMPANY_NAME], $temp)) {
						return "公司同事";
					}
				}
			}
		}

		// 异性有缘人
		$gender1 = UCModUserInfo::getUser($user1_id)->getValue(USERINFO_GENDER);
		$gender2 = UCModUserInfo::getUser($user2_id)->getValue(USERINFO_GENDER);
		if ($gender1 != $gender2) {
			return "异性有缘人";
		}

		// 找不到
		return null;
	}
}
?>